﻿@page "/image"
@page "/image/{ImageID}"

@using Damselfly.Core.Constants

@inject NavigationService navContext
@inject NavigationManager NavigationManager
@inject ViewDataService ViewDataService
@inject IUserConfigService userConfigService
@inject IRescanService rescanService
@inject IImageCacheService imageCache
@inject IJSRuntime JsRuntime
@inject ClientBasketService basketService

@using System.Net
@implements ICropHelper

<div class="damselfly-imageview" @ref="ImageView" id="test-container-keydown" style="outline: none;" tabindex="0" @onkeydown="OnKeyDown">
    @if ( CurrentImage == null )
    {
        <div class="col">
            <p>
                <em>Error. Image not found!</em>
            </p>
        </div>
    }
    else
    {
        <div class="damselfly-imagetools">
            <div class="damselfly-imagetitlenav">
                <NavBack/>
            </div>
            <div class="damselfly-imagebuttons">
                <ToolbarButton IconStyle="fa-chevron-left" OnClickCallback="@Prev" Enabled="@PrevEnabled" title="Previous Image"/>
                <ToolbarButton IconStyle="fa-object-ungroup" OnClickCallback="@ToggleShowObjects" Selected="@ShowObjects" title="Show AI Objects/Faces"/>
                <AuthorizeView Policy="@PolicyDefinitions.s_IsDownloader">
                    <ToolbarButton IconStyle="fa-download" OnClickCallback="@DownloadImage" title="Download Image"/>
                </AuthorizeView>
                <AuthorizeView Policy="@PolicyDefinitions.s_IsEditor">
                    <ToolbarButton IconStyle="fa-sync-alt" OnClickCallback="@RefreshImage" title="Re-scan Image Metadata"/>
                </AuthorizeView>
                <ToolbarButton IconStyle="fa-chevron-right" OnClickCallback="@Next" Enabled="@NextEnabled" title="Next Image"/>

                <!--ToolbarButton IconStyle="fa-facebook" title="Share on Facebook" onclick="
                window.open(
                '@FaceBookShareUrl',
                'facebook-share-dialog',
                'width=626,height=436');
                return false;" />
                <ToolbarButton IconStyle="fa-crop" Enabled="false" title="Crop/Select Image" /-->
                &nbsp; &nbsp;

                <ToolbarButton IconStyle="fa-search-minus" OnClickCallback="@ZoomOut" Enabled="@CanZoomOut" title="Zoom Out"/>
                <input type="range" min="1" max="8" step="0.2" @bind-value="ZoomRange" @bind-value:event="oninput" title="@ZoomTitle" class="zoom-slider" disabled="@ZoomDisabled"/>
                <ToolbarButton IconStyle="fa-search-plus" OnClickCallback="@ZoomIn" Enabled="@CanZoomIn" title="Zoom In"/>
                <ToolbarButton IconStyle="fa-expand" OnClickCallback="@ResetZoom" title="Reset Zoom" Enabled="@(!ZoomDisabled)"/>
                @if( EnableImageEditing )
                {
                    <ToolbarButton IconStyle="fa-edit" OnClickCallback="@BeginEdit" title="Edit Image" Enabled="@(!Editing)"/>
                    @if ( Editing )
                    {
                        <MudButton Color="Color.Primary" OnClick="@SaveEdits">Save</MudButton>
                        <MudButton Color="Color.Secondary" OnClick="@CancelEdit">Cancel</MudButton>
                    }
                }
            </div>
            <div class="damselfly-imagetitle" title="@CurrentImage.FullPath">
                <h4>
                    @CurrentImage.FileName
                </h4>
            </div>
        </div>

        <MudSwipeArea OnSwipeEnd="OnSwipe">
            <ImagePreview @ref="theImagePreview" @key="@ImageID" Editing=Editing Image="@CurrentImage"/>
        </MudSwipeArea>
    }
</div>

@code {

    [Parameter] public string ImageID { get; set; }

    private Image CurrentImage;
    private int? nextImage;
    private int? prevImage;
    private ElementReference ImageView;
    private bool Editing = false;
    private bool EnableImageEditing = false;

    private bool ShowObjects => theImagePreview == null ? false : theImagePreview.ShowObjects;

    private ImagePreview theImagePreview;
    public string ImgKey => $"prev{CurrentImage.ImageId}";
    public string ImgPreviewKey => $"{CurrentImage.ImageId}";
    public string ZoomTitle => ShowObjects ? "Disable Objects/Faces to Zoom" : "Zoom Level (press up/down to change)";
    public string ImageUrl { get; set; }
    public string ImageUrlHighRes { get; set; }

    public CropJsHelper JsHelper { get; set; }

    private bool NextEnabled => nextImage != null && nextImage != CurrentImage.ImageId;
    private bool PrevEnabled => prevImage != null && prevImage != CurrentImage.ImageId;
    private string PrevImageIDUrl => $"/image/{prevImage}";
    private string NextImageIDUrl => $"/image/{nextImage}";

    private async Task ZoomIn()
    {
        await theImagePreview!.ZoomIn();
    }

    private async Task ZoomOut()
    {
        await theImagePreview!.ZoomOut();
    }

    private async Task ResetZoom()
    {
        await theImagePreview!.ResetZoom();
    }

    private double ZoomRange
    {
        get => theImagePreview == null ? 0 : theImagePreview.ZoomRangeValue;
        set
        {
            if ( theImagePreview != null ) theImagePreview.ZoomRangeValue = value;
        }
    }

    private bool CanZoomIn => ZoomRange < 5.0 && !ZoomDisabled;
    private bool CanZoomOut => ZoomRange > 1.0 && !ZoomDisabled;
    private bool ZoomDisabled => ShowObjects;

    private async Task OnSwipe( SwipeEventArgs args)
    {
        switch( args.SwipeDirection )
        {
            case SwipeDirection.LeftToRight:
                Next();
                break;
            case SwipeDirection.RightToLeft:
                Prev();
                break;
            case SwipeDirection.TopToBottom:
                await ZoomIn();
                break;
            case SwipeDirection.BottomToTop:
                await ZoomOut();
                break;
        }
    }

    protected override void OnInitialized()
    {
        EnableImageEditing = userConfigService.GetBool(ConfigSettings.EnableImageEditing);

        base.OnInitialized();
    }

    private void BeginEdit()
    {
        Editing = true;
    }

    private void CancelEdit()
    {
        Editing = false;
    }

    private void SaveEdits()
    {
        Editing = false;
    }

    public string FaceBookShareUrl
    {
        get
        {
            var baseUrl = new Uri(NavigationManager.BaseUri);

            var url = new Uri(baseUrl, $"/thumb/{ThumbSize.Large}/{ImageID}");
            var imageUrl = WebUtility.UrlEncode(url.ToString());
            return $"https://www.facebook.com/sharer/sharer.php?u={imageUrl}";
        }
    }

    protected override async Task OnParametersSetAsync()
    {
        await SetUpNavigation();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if ( firstRender )
        {
            ViewDataService.SetSideBarState(new ViewDataService.SideBarState { ShowImageProps = true, ShowTags = true, ShowMap = true });

            //this.JsHelper = new CropJsHelper(this);
            //await JsRuntime.InvokeAsync<string>("doImageCrop", "theImage", DotNetObjectReference.Create(JsHelper));

            await SetUpNavigation();

            _ = ImageView.FocusAsync();
        }
    }

    private void ToggleShowObjects()
    {
        theImagePreview.ToggleShowObjects();
    }

    protected void ReplaceUrl(ProgressEventArgs args)
    {
        Logging.Log("Replacing Image URL");
        ImageUrl = ImageUrlHighRes;
        StateHasChanged();
    }


    [JSInvokable]
    // Debugging assistant to help us differentiate between JS calls and other data loads
    public void CompleteCrop(CropData cropData)
    {
        Logging.Log($"Crop complete: {cropData.Left}");
    }

    protected async Task SetUpNavigation()
    {
        if ( int.TryParse(ImageID, out var imageId) )
        {
            CurrentImage = await imageCache.GetCachedImage(imageId);
            navContext.CurrentImage = CurrentImage;

            // TODO: Fix nullref here
            ImageUrl = CurrentImage.ThumbUrl(ThumbSize.Medium);
            ImageUrlHighRes = CurrentImage.ThumbUrl(ThumbSize.ExtraLarge);
            ;

            nextImage = await navContext.GetNextImage(true);
            prevImage = await navContext.GetNextImage(false);

            StateHasChanged();
        }
    }

    private void Next()
    {
        if ( nextImage >= 0 && nextImage != CurrentImage.ImageId )
            NavigationManager.NavigateTo($"/image/{nextImage}");
    }

    private void Prev()
    {
        if ( prevImage >= 0 && prevImage != CurrentImage.ImageId )
            NavigationManager.NavigateTo($"/image/{prevImage}");
    }

    public void RefreshImage()
    {
        _ = rescanService.MarkImagesForRescan(RescanTypes.Indexing, new List<int> { CurrentImage.ImageId });
    }

    public async Task DownloadImage()
    {
        try
        {
            await JsRuntime.InvokeAsync<string>("downloadFile", CurrentImage.DownloadImageUrl);
        }
        catch ( Exception ex )
        {
            Logging.LogError("Exception: " + ex.Message);
        }
    }

    async Task OnKeyDown(KeyboardEventArgs e)
    {
        if ( e.Key == "ArrowRight" )
        {
            Next();
        }
        else if ( e.Key == "ArrowLeft" )
        {
            Prev();
        }
        else if ( e.Key == "Escape" )
        {
            if ( theImagePreview.ZoomRangeValue > 2.0 )
                await theImagePreview.ResetZoom();
            else
                NavigationManager.NavigateTo("/");
        }
        else if ( e.Key == "ArrowUp" )
        {
            await theImagePreview.ZoomIn();
        }
        else if ( e.Key == "ArrowDown" )
        {
            await theImagePreview.ZoomOut();
        }
        else if ( e.Key == " " )
        {
            var currentState = basketService.IsInCurrentBasket(CurrentImage);
            await basketService.SetImageBasketState(!currentState, new[] { CurrentImage.ImageId });
        }
    }

}